package com.wolfpire.proms.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.wolfpire.proms.dao.ProjectIndexCountDao;
import com.wolfpire.proms.model.ProjectIndexCount;
import com.wolfpire.system.common.Page;
import com.wolfpire.system.common.base.dao.impl.BaseHibernateDao;

@Repository("projectIndexCountDao")
public class ProjectIndexCountDaoImpl extends BaseHibernateDao<ProjectIndexCount, Long> implements ProjectIndexCountDao {

	@Override
	public Page<ProjectIndexCount> findProjectIndexCounts(Page<ProjectIndexCount> page, ProjectIndexCount filterProjectIndexCount) {
		Criterion[] criterions = createFilter(filterProjectIndexCount, null, true);
		int totalCount = this.findIntByCriteria(criterions);
		page.setTotalCount(totalCount);
		
		if (0 < totalCount) {
			Criteria c = createCriteria(criterions);
			c.addOrder(Order.asc("seq"));
			c.addOrder(Order.asc("id"));
			c = this.setPageParameter(c, page);
			@SuppressWarnings({ "unchecked" })
			List<ProjectIndexCount> result = c.list();
			page.setDataList(result);
		}
		return page;
	}

	private Criterion[] createFilter(ProjectIndexCount filterProjectIndexCount, String type, boolean cascadeParentId) {
		if (null == filterProjectIndexCount) {
			return null;
		}
		List<Criterion> criterions = new ArrayList<Criterion>();
		if (null != filterProjectIndexCount.getId()) {
			criterions.add(Restrictions.eq("id", filterProjectIndexCount.getId()));
		}
		if (!StringUtils.isBlank(filterProjectIndexCount.getName())) {
			criterions.add(Restrictions.like("name", filterProjectIndexCount.getName(), MatchMode.ANYWHERE));
		}
		if (null != filterProjectIndexCount.getParentId()) {
			if (cascadeParentId) {
				List<Long> ids = this.findAllIds(filterProjectIndexCount.getParentId());
//				ids.add(filterProjectIndexCount.getParentId());
				criterions.add(Restrictions.or(Restrictions.in("parentId", ids), Restrictions.eq("id", filterProjectIndexCount.getParentId())));
			} else {
				criterions.add(Restrictions.eq("parentId", filterProjectIndexCount.getParentId()));
			}
		} else {
			if ("tree".equals(type)) {
				criterions.add(Restrictions.isNull("parentId"));
			}
		}
		if (!StringUtils.isBlank(filterProjectIndexCount.getRemark())) {
			criterions.add(Restrictions.like("remark", filterProjectIndexCount.getRemark(), MatchMode.ANYWHERE));
		}
		if (null != filterProjectIndexCount.getDelFlag()) {
			criterions.add(Restrictions.eq("delFlag", filterProjectIndexCount.getDelFlag()));
		}
		return criterions.toArray(new Criterion[criterions.size()]);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ProjectIndexCount> list(ProjectIndexCount projectIndex) {
		Criteria c = createCriteria(createFilter(projectIndex, "tree", false));
		c.addOrder(Order.asc("seq"));
		c.addOrder(Order.asc("id"));
		return c.list();
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public List<Long> findAllIds(Long id) {
		String querySql = " SELECT id FROM t_project_index WHERE FIND_IN_SET(id, queryChildrenProjectIndexCount(:projectIndexId)) ";
		List propertyValues = new ArrayList();
		List<String> propertyNames = new ArrayList<String>();
		propertyNames.add("projectIndexId");
		propertyValues.add(id);
		SQLQuery query = this.createSqlQuery(querySql, propertyNames, propertyValues);
//		query.addEntity(Long.class);
		List list = query.list();
		List<Long> rs = new ArrayList<Long>();
		if (CollectionUtils.isNotEmpty(list)) {
			for (Object o : list) {
				rs.add(new Long(o.toString()));
			}
		}
		return rs;
	}

	@SuppressWarnings("unused")
	@Override
	public void updateTaskCount() {
		String count_col ="id            ,"+    
				"create_user_id,"+    
				"create_time   ,"+    
				"del_flag      ,"+    
				"name          ,"+    
				"parent_id     ,"+    
				"remark        ,"+    
				"requirement   ,"+    
				"seq           ,"+    
				"update_time   ,"+    
				"update_user_id,"+    
				"code          ,"+    
				"leaf          ,"+    
				"weight        ,"+    
				"plan_amount   ,"+    
				"end_time      ,"+    
				"expect_result ,"+    
				"path          ,"+    
				"actor_id      ,"+    
				"actor_name    ,"+    
				"task_count,child_count    " ;
		String col ="id            ,"+    
				"create_user_id,"+    
				"create_time   ,"+    
				"del_flag      ,"+    
				"name          ,"+    
				"parent_id     ,"+    
				"remark        ,"+    
				"requirement   ,"+    
				"seq           ,"+    
				"update_time   ,"+    
				"update_user_id,"+    
				"code          ,"+    
				"leaf          ,"+    
				"weight        ,"+    
				"plan_amount   ,"+    
				"end_time      ,"+    
				"expect_result ,"+    
				"path          ,"+    
				"actor_id      ,"+    
				"actor_name    " ;
		
		//step 1 更新新的指标
		String insertNewIndex = "insert into t_project_index_count (id ,create_user_id,create_time   ,del_flag      ,name          ,parent_id     ,remark        ,requirement   ,seq           ,update_time   ,update_user_id,code          ,leaf          ,weight        ,plan_amount   ,end_time      ,expect_result ,path          ,actor_id      ,actor_name    ,task_count     ,child_count) select id ,create_user_id,create_time   ,del_flag      ,name          ,parent_id     ,remark        ,requirement   ,seq           ,update_time   ,update_user_id,code          ,leaf          ,weight        ,plan_amount   ,end_time      ,expect_result ,path          ,actor_id      ,actor_name,0,0     from t_project_index t where t.id not in (select id from t_project_index_count)";
		this.executeSql(insertNewIndex.toString(),  new Object[]{});
		//step 2 同步删除的指标
		String sysDelflag ="update t_project_index_count c,t_project_index t set c.del_flag = t.del_flag where c.id = t.id ";
		this.executeSql(sysDelflag.toString(),  new Object[]{});
		
		//统计每个指标下的任务
		String countIndexTask = "update t_project_index_count c ,"
				+ "(select count(*) count ,project_index_id from t_task group by project_index_id) t "
				+ "set c.task_count = t.count where c.id = t.project_index_id and c.del_flag =1";
		
		this.executeSql(countIndexTask.toString(),  new Object[]{});
		
		String countChild = "update t_project_index_count p ,"
				+ "(select sum(task_count) c_task,sum(child_count) c_child ,parent_id from t_project_index_count  group by parent_id) c "
				+ "set p.child_count = c.c_task+c.c_child where p.id = c.parent_id";
		//按有5层结构预估统计
		for (int i = 0; i < 5; i++) {
			this.executeSql(countChild.toString(),  new Object[]{});
		}
		
	}

}
